package cn.sc.summer.mybatis.context;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.sc.summer.mybatis.enums.DataSourceEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * 类名：数据源切换线程工具类
 *
 * @author a-xin
 * @date 2024/2/1 14:54
 */
@Slf4j
public class DynamicDataSourceContext extends AbstractRoutingDataSource implements DisposableBean {

    private static final ThreadLocal<String> DATA_SOURCE_THREAD = new ThreadLocal<>();

    private final Map<Object, Object> targetDataSources;

    /**
     * 决定使用哪个数据源之前需要把多个数据源的信息以及默认数据源信息配置好
     *
     * @param targetDataSources       目标数据源
     * @param defaultTargetDataSource 默认数据
     */
    public DynamicDataSourceContext(Map<Object, Object> targetDataSources, DataSource defaultTargetDataSource) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
        this.targetDataSources = targetDataSources;
    }

    @Override
    public Object determineCurrentLookupKey() {
        String dataSource = DATA_SOURCE_THREAD.get();
        if (CharSequenceUtil.isBlank(dataSource)) {
            return DataSourceEnum.MASTER.getType();
        }
        log.debug("The execute data source ::: {}", dataSource);
        return dataSource;
    }

//    /**
//     * 重写方法，获取的是动态代理对象
//     */
//    @Override
//    public @NonNull Connection getConnection() {
//        return (Connection) Proxy.newProxyInstance(this.getClass().getClassLoader(),
//                new Class[]{Connection.class},
//                new RoutingProxyHandler(this));
//    }

    /**
     * 获取真正的Connection连接对象(其实也是数据源厂商实现的代码连接)
     */
    public Connection getRealConnection() throws SQLException {
        return super.getConnection();
    }

    /**
     * 设置需要使用的数据源信息
     *
     * @param dbType 数据源类型
     */
    public static void setDataSource(String dbType) {
        DATA_SOURCE_THREAD.set(dbType);
    }

    /**
     * 获取当前已设置数据源信息
     */
    public static String getDataSource() {
        return DATA_SOURCE_THREAD.get();
    }

    /**
     * 清楚数据源信息
     */
    public static void clearDataSource() {
        DATA_SOURCE_THREAD.remove();
    }

    /**
     * 获取所有动态数据源信息
     */
    public Map<Object, Object> getTargetDataSources() {
        return CollUtil.isEmpty(this.targetDataSources) ? new HashMap<>() : this.targetDataSources;
    }

    /**
     * Invoked by the containing {@code BeanFactory} on destruction of a bean.
     */
    @Override
    public void destroy() {
        DATA_SOURCE_THREAD.remove();
    }
}


